﻿using System;
using System.Collections.Generic;
using Lucene.Net.Analysis;

namespace Lucene.Linq.Mapping
{
    /// <summary>Lucene Index Document Details</summary>
    public class DocumentDetails
    {
        #region Fields/Properties

        /// <summary>The default analyzer for the document </summary>
        private Analyzer _defaultAnalyzer;

        /// <summary>The name of the index document</summary>
        public string Name { get; set; }

        /// <summary>The analyzer used for indexing and searching</summary>
        public Analyzer Analyzer { get; private set; }

        /// <summary>
        /// The field details for the document
        /// </summary>
        public IEnumerable<FieldDetails> Fields { get; private set; }

        #endregion

        #region Ctors

        /// <summary>Creates a Lucene.Net index document details</summary>
        /// <param name="name">The name of the index document</param>
        /// <param name="defaultAnalyzerType">The default analyzer to be used when indexing or searching</param>
        /// <param name="fields">The fields details enumerable</param>
        public DocumentDetails(string name, Type defaultAnalyzerType, IEnumerable<FieldDetails> fields)
        {
            if (name == null) throw new ArgumentNullException("name");
            if (defaultAnalyzerType == null) throw new ArgumentNullException("defaultAnalyzerType");
            if (fields == null) throw new ArgumentNullException("fields");

            Name = name;
            Fields = fields;
            Init(defaultAnalyzerType);
        }

        #endregion

        private static Analyzer InstantiateAnalyzerFromType(Type type)
        {
            if (type == null)
                throw new ArgumentNullException("type");

            var result = Activator.CreateInstance(type) as Analyzer;

            if (result == null)
                throw new ArgumentException(type.Name + " is not an Lucene.Net Analyzer type");

            return result;
        }

        private void Init(Type defaultType)
        {
            if (defaultType == null)
                throw new ArgumentNullException("defaultType");


            // create default analyzer instance
            _defaultAnalyzer = InstantiateAnalyzerFromType(defaultType);

            var wrapper = new PerFieldAnalyzerWrapper(_defaultAnalyzer);

            foreach (FieldDetails fd in Fields)
            {
                if (fd.Field.Analyzer != null)
                {
                    Analyzer fieldAnalyzer = InstantiateAnalyzerFromType(fd.Field.Analyzer);
                    if (fieldAnalyzer != null)
                    {
                        wrapper.AddAnalyzer(fd.Name, fieldAnalyzer);
                    }
                }
            }

            Analyzer = wrapper;
        }
    }
}